#ifndef _485_PROTOCOL_H
#define _485_PROTOCOL_H

#include <stdint.h>
#include <stdbool.h>
#include <config.h>
#include "bluetooth_board.h"
#include "device_parameter.h"
//与门禁io板的协议相关定义

/*** 枚举类型定义 ***/
//格式	帧头	数据长度（数据长度）（2byte）	命令(1byte)	源地址（6byrte）	目标地址（6byrte）	数据(nbyte)	累加校验(从帧头累加至数据最后一字节，后取数据后8位)(1byte)
/**
 * @brief 协议命令
 */
typedef enum {
   // 打开对应楼层电梯
   CMD_OPEN_FOOR = 0x01, 
   // ota固件传输
   CMD_FIRMWARE_TRANS = 0x02,
   // 查询ota状态
   CMD_QUERY_OTA_STATUS = 0x03,
   // 获取版本号
   CMD_GET_VERSION = 0x04,
   // 开启紧急模式
   CMD_OPEN_EMERGENCY_MODE = 0x05,
   // 查询主板地址
   CMD_QUERY_IO_BOARD_MAC_ADDRESS = 0x06,
   // 设置主板自检
   CMD_SET_BOARD_SELF_TEST = 0x07
}ProtocolCmd_t;

/**
 * @brief 解析结果
 */
typedef enum
{
    NO_ERROR,
    ERROR_FRAME_HEADER_ERROR, // 帧头错误
    ERROR_FRAME_LENGTH_ERROR, // 帧长错误
    ERROR_FRAME_CHECKSUM_ERROR, // 帧校验错误
    ERROR_DESTIN_ADDR_ERROR, // 目的地址错误
    ERROR_NULL_PTR, // 空指针错误
}ParsingResult_t;

//1：ota接收成功 2：ota接收失败 3：ota数据校验失败 4：固件版本出错
typedef enum{
    OTA_RECV_SUCCESS = 1,
    OTA_RECV_FAIL = 2,
    OTA_DATA_CHECKSUM_FAIL = 3,
    OTA_FIRMWARE_VERSION_ERROR = 4,
}OtaRecStatus_t;



/*** 枚举类型定义 结束 ***/

/*** 宏定义 ***/

#define FRAME_HEADER1           0x55 // 帧头1
#define FRAME_HEADER2           0xAA // 帧头2

#define MAX_BUFFER_SIZE         512 // 最大缓冲区大小

#define MESSAGE_DATA_PACKET_LENGTH MAX_BUFFER_SIZE // 消息数据包长度
#define MAX_TABLE_SIZE (CMD_OPEN_EMERGENCY_MODE+1) //协议表最大长度

#define ELECTOR_SUM_FLOOR_NUM_BUFFER_SIZE   16 // 电梯总楼层数





/*** 宏定义 结束 ***/

/*** 类型定义 ***/

typedef struct{
    uint8_t DirectModeFlag;// 直达模式
    uint8_t User; //用户类型
    uint8_t ElectorFloorData[ELECTOR_SUM_FLOOR_NUM_BUFFER_SIZE];//电梯楼层数据
}ElectorData_t;

/**
 * @brief 构建响应帧的函数指针
 * 
 * @param ptr 输入数据
 * @param data 输出数据
 * @param len 输出数据长度
 */
typedef bool (*BuildFrameCallback_t)(void* ptr, uint8_t* data, uint16_t *len);

/**
 * @brief 解析数据帧的函数指针
 * 
 * @param DataOut 输出数据
 * @param DataSizeOut 输出数据长度
 * @return 返回值代表是否组建响应包回复，true表示回复，false表示不回复 
 */
typedef uint8_t (*ParseFrameCallback_t)(uint8_t* DataOut, uint16_t DataSizeOut);

/**
 * @brief 报文解析结果
 *
 */
typedef enum
{
  RS485_PARSING_ERROR,            // 报文解析错误
  RS485_PARSING_SUCCESS,          // 报文解析成功
  RS485_PARSING_NO_KEYWORD_FOUND, // 没有找到关键字
} RS485MessageParsingResult_t;
/*** 类型定义 结束 ***/



/*** 结构体定义 ***/

/**
 * @brief 协议帧表
 */
typedef struct
{                         
  ParseFrameCallback_t ParseFrameCallback;           // 解析数据帧的回调函数指针
  BuildFrameCallback_t BuildResponseFrameCallback; // 构建响应帧的回调函数指针
} ProtocolFrameTable_t;

/**
 * @brief 串口数据缓冲区的定义
 *
 */
typedef struct
{
  uint16_t DataSize;                              // 数据长度
  uint8_t DataBuff[MAX_BUFFER_SIZE];               // 收发数据流
  bool RecivingFlag;                               // 接收标志
  bool SendingFlag;                                 // 发送标志
  bool SendCompleteFlag;                         // 发送完成标志
  bool ReciveCompleteFlag;                       // 接收完成标志
} MyDataPacket_t;



/*** 结构体定义 结束 ***/



/*** 函数的外部声明 ***/   

/**
 * @brief 校验报文有效性
 * 
 * @param DataBuffIn  输入数据缓冲区
 * @param AttachedDataOut 输出数据缓冲区
 * @param AttachedDataSizeOut 输出数据长度
 * @param ParsingResult 解析结果
 * @param CurrentCommandOut 当前命令
 * @return true 
 * @return false 
 */
extern bool VerifyMessageValidity(uint8_t *DataBuffIn, uint8_t * AttachedDataOut, uint16_t*AttachedDataSizeOut, ParsingResult_t* ParsingResult, uint16_t* CurrentCommandOut);

/**
 * @brief 计算校验和
 * 
 * @param data 输入数据
 * @param length 输入数据长度
 * @return uint8_t 校验和
 */
extern uint8_t calculateChecksum(uint8_t* data, uint8_t length); 


// todo: CMD_OPEN_FOOR
/**
 * @brief 构建打开指定楼层电梯的命令
 * 
 * @param dataIn 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool BuildOpenSpecificFoorFrameCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief 解析打开指定楼层电梯的命令
 * 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern uint8_t ParsingOpenSpecificFoorFrameCallback(uint8_t *data, uint16_t len);

// todo: CMD_FIRMWARE_TRANS
/**
 * @brief 构建固件传输命令
 *
 * @param dataIn
 * @param data
 * @param len
 * @return true
 * @return false
 */
extern bool BuildFirmwareTransFrameCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief 解析固件传输命令
 *
 * @param dataIn
 * @param len
 * @return true
 * @return false
 */
extern bool ParsingFirmwareTransFrameCallback(uint8_t *data, uint16_t len);


// todo: CMD_GET_VERSION
/**
 * @brief 构建获取版本号命令
 *
 * @param dataIn
 * @param data
 * @param len
 * @return true
 * @return false
 */
extern bool BuildGetVersionFrameCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief 解析获取版本号命令
 *
 * @param dataIn
 * @param len
 * @return true
 * @return false
 */
extern bool ParsingGetVersionFrameCallback(uint8_t *data, uint16_t len);

// todo: CMD_OPEN_EMERGENCY_MODE
/**
 * @brief 构建开启紧急模式命令
 *
 * @param dataIn
 * @param data
 * @param len
 * @return true
 * @return false
 */
extern bool BuildOpenEmergencyModeFrameCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief 解析开启紧急模式命令
 *
 * @param dataIn
 * @param len
 * @return true
 * @return false
 */
extern bool ParsingOpenEmergencyModeFrameCallback(uint8_t *data, uint16_t len);

/**
 * @brief  构建查询io板固件状态命令
 * 
 * @param dataIn 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool BuildQueryIoBoardFirmwareStatusCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief  解析查询io板固件状态命令
 * 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool ParsingQueryIoBoardFirmwareStatusCallback(uint8_t *data, uint16_t len);

/**
 * @brief  构建查询io板mac地址命令
 * 
 * @param dataIn 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool BuildQueryIoBoardMacAddressCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief  解析查询io板mac地址命令
 * 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool ParsingQueryIoBoardMacAddressCallback(uint8_t *data, uint16_t len);

/**
 * @brief  构建设置io板自测试命令
 * 
 * @param dataIn 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool BuildSetBoardSelfTestFrameCallback(void *dataIn, uint8_t *data, uint16_t *len);

/**
 * @brief  解析设置io板自测试命令
 * 
 * @param data 
 * @param len 
 * @return true 
 * @return false 
 */
extern bool ParsingSetBoardSelfTestFrameCallback(uint8_t *data, uint16_t len);


/*** 函数的外部声明 结束 ***/



#endif